{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "initial_id",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-11-21T13:31:25.022339600Z",
     "start_time": "2023-11-21T13:31:25.016155200Z"
    }
   },
   "outputs": [],
   "source": [
    "from advisor_backend.interface import Interface\n",
    "import matplotlib.pyplot as plt\n",
    "import pandas as pd"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "57d17a21205c3c5e",
   "metadata": {
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "source": [
    "# 总体性能拆解分析\n",
    "### 1. 数据准备\n",
    "我们当前支持Ascend PyTorch Profiler工具采集到的性能数据，您需要采集到的profiling_path路径，指定到*_ascend_pt。\n",
    "\n",
    "### 2. 拆解项说明\n",
    "将整体耗时拆解为计算（Computing Time）、通信（Uncovered Communication Time）和空闲（Free Time）3个部分。\n",
    "\n",
    "1）. Computing Time：指device在执行计算的耗时，若存在多条流并行计算的情况，对于耗时重叠部分只会计算一次\n",
    "\n",
    "计算耗时细分如下\n",
    "\n",
    "    Cube Time：Cube算子耗时，该耗时占Computing Time的60%以上更能充分发挥NPU的算力\n",
    "    Vector Time：Vector算子耗时\n",
    "    Flash Attention Time(Forward)：Flash Attention算子前向耗时\n",
    "    Flash Attention Time(Backward)：Flash Attention算子反向耗时\n",
    "    Oter Time：AI CPU、DSA、TensorMove等其他算子耗时\n",
    "    \n",
    "2）. Uncovered Communication Time：未被计算掩盖的通信耗时，即总通信耗时减去通信与计算并行执行的耗时\n",
    "\n",
    "3）. Free Time：指device既不在通信又不在计算的时间，空闲耗时 = 整体耗时 - 计算耗时 - 未被计算掩盖的通信耗时，该时间包含下发调度、SDMA时间（内存拷贝时间）。该耗时建议保持在10%以下\n",
    "\n",
    "空闲耗时细分如下\n",
    "\n",
    "    SDMA Time：内存拷贝任务的耗时\n",
    "\n",
    "<font color=red>特别说明：通信（Uncovered Communication Time）和空闲（Free Time）耗时会受profiling性能膨胀的影响，以L0 + NPU采集的profiling为准。</font>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "36b7a24cc7ca5da2",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-11-21T12:53:38.379699800Z",
     "start_time": "2023-11-21T12:53:38.363755900Z"
    },
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [],
   "source": [
    "# 数据准备 EDIT THE PROFILING DATA PATH\n",
    "profiling_path = \"YOUR PATH\"\n",
    "# 若您有GPU上采集到的性能数据，可将NPU的性能数据与GPU之间进行对比，分析性能差距。输入GPU的性能数据路径\n",
    "gpu_profiling_path = \"\"    #默认为空，若有则可填写\n",
    "interface = Interface(profiling_path)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cf832ac2e0dfa30f",
   "metadata": {
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "source": [
    "## 1) 性能拆解分析"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "40aac93278dd6e34",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2023-11-21T12:53:41.815599700Z",
     "start_time": "2023-11-21T12:53:41.783393700Z"
    },
    "jupyter": {
     "outputs_hidden": false
    },
    "scrolled": false
   },
   "outputs": [],
   "source": [
    "print(\"Start performance analysis, please wait...\")\n",
    "dataset = interface.get_data('overall', 'summary', base_collection_path=gpu_profiling_path)\n",
    "data = dataset.get('data', {}) or {}\n",
    "bottleneck = dataset.get('bottleneck', {}) or {}\n",
    "print(\"Performance analysis is complete, you can edit the data to show what you want.\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3f353506",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 等待性能分析完成后再查看数据"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "cd3fceda-49f0-439f-9c54-cc31490fc99e",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 600x600 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The Model E2E Time is 9.352s.\n",
      " --Computing Time is 6.273s\n",
      " --Uncovered Communication Time is 0.464s\n",
      " --Free Time is 2.615s\n"
     ]
    }
   ],
   "source": [
    "# 饼图展示计算、通信、空闲耗时的占比\n",
    "overall_data = data.get(\"overall_data\", {})\n",
    "plt.figure(figsize=(6, 6))  #设置饼图大小\n",
    "plt.pie(x=overall_data.values(), labels=overall_data.keys(), explode=[0.01]*len(overall_data), autopct=\"%1.1f%%\")\n",
    "plt.title(\"Model Profiling Time Distribution\")\n",
    "plt.show()\n",
    "print(bottleneck.get(\"overall_data\", \"\"))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "6a1d82fb-a31b-49ab-a859-6d4bb898c512",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "  Computing Time Subtype  Duration(s) Duration Ratio  Kernel Number\n",
      "0              Cube Time        3.956         63.06%            584\n",
      "1            Vector Time        1.994         31.79%           5224\n",
      "\n",
      "Computing Time is 6.273s\n",
      " if you want more detailed advice please go to compute_perf_analysis.ipynb\n"
     ]
    }
   ],
   "source": [
    "# 展示计算细分耗时，NPU开启level1或level2，aic_metric设为PipeUtilization\n",
    "compute_time = data.get(\"computing\", {})\n",
    "print(pd.DataFrame(compute_time))\n",
    "print(\"\\n\", bottleneck.get(\"computing\", \"\"))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "35df1f13",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Empty DataFrame\n",
      "Columns: []\n",
      "Index: []\n",
      "\n"
     ]
    }
   ],
   "source": [
    "# 展示通信细分耗时，通信耗时受profiling性能膨胀的影响，以L0 + NPU采集的profiling为准\n",
    "communication_time = data.get(\"communication\", {})\n",
    "print(pd.DataFrame(communication_time))\n",
    "print(\"\\n\", bottleneck.get(\"communication\", \"\"))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "c5e6034e",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "  Free Time Subtype  Duration(s) Duration Ratio  Kernel Number\n",
      "0         SDMA Time        0.073          2.79%            852\n",
      "\n",
      "Free Time is 2.615s\n",
      " if you want more detailed advice please go to timeline_perf_analysis.ipynb\n"
     ]
    }
   ],
   "source": [
    "# 展示空闲细分耗时，该耗时受profiling性能膨胀的影响，以L0 + NPU采集的profiling为准\n",
    "free_time = data.get(\"free\", {})\n",
    "print(pd.DataFrame(free_time))\n",
    "print(\"\\n\", bottleneck.get(\"free\", \"\"))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3511befaff513e8e",
   "metadata": {
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "source": [
    "## 2）有对标的GPU数据"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "2a1e617d2a117125",
   "metadata": {
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "+----------------------------------------------------------------------------------------------------------------+\n",
      "|                                       Model Profiling Time Distribution                                        |\n",
      "+-----+----------------+------------------+----------------+------------------------------+-----------+----------+\n",
      "|     | Cube Time(Num) | Vector Time(Num) | Computing Time | Uncovered Communication Time | Free Time | E2E Time |\n",
      "+-----+----------------+------------------+----------------+------------------------------+-----------+----------+\n",
      "| GPU |  3.149s(582)   |   1.346s(3433)   |     4.748s     |            0.024s            |   0.051s  |  4.840s  |\n",
      "| NPU |  3.956s(584)   |   1.994s(5224)   |     6.273s     |            0.464s            |   2.615s  |  9.352s  |\n",
      "+-----+----------------+------------------+----------------+------------------------------+-----------+----------+\n"
     ]
    }
   ],
   "source": [
    "# 有可对比的GPU数据情况下，展示比对结果\n",
    "from prettytable import PrettyTable\n",
    "comparison_result = data.get(\"comparison_result\", {})\n",
    "if not comparison_result:\n",
    "    print(\"Invalid comparison data, you need to set the gpu_profiling_path.\")\n",
    "if comparison_result:\n",
    "    for sheet_name, data in comparison_result.items():\n",
    "        if data.get(\"rows\", []):\n",
    "            table = PrettyTable()\n",
    "            table.title = sheet_name\n",
    "            table.field_names = data.get(\"headers\", [])\n",
    "            for row in data.get(\"rows\", []):\n",
    "                table.add_row(row)\n",
    "            print(table)\n",
    "    print(bottleneck.get(\"comparison_result\", \"\"))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0d968851",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
